package com.youbug.mall.product_pms.service.impl;

import com.youbug.common.to.SkuHasStockTo;
import com.youbug.common.to.SkuReductionTo;
import com.youbug.common.to.SpuBoundTo;
import com.youbug.common.to.es.SkuEsModel;
import com.youbug.common.vo.R;
import com.youbug.mall.product_pms.constant.ProductConstant;
import com.youbug.mall.product_pms.entity.*;
import com.youbug.mall.product_pms.feign.ICouponFeignService;
import com.youbug.mall.product_pms.feign.ISearchFeignService;
import com.youbug.mall.product_pms.feign.IWareFeignService;
import com.youbug.mall.product_pms.feign.PmsToSmsThreadPool;
import com.youbug.mall.product_pms.mapper.PmsSpuInfoMapper;
import com.youbug.mall.product_pms.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youbug.mall.product_pms.vo.*;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.youbug.mall.product_pms.entity.PmsSpuInfo;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import com.youbug.common.vo.QueryVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.util.StringUtils;

import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * spu信息 服务实现类
 * </p>
 *
 * @author youbug
 * @since 2024-04-21
 */
@Service
public class PmsSpuInfoServiceImpl extends ServiceImpl<PmsSpuInfoMapper, PmsSpuInfo> implements IPmsSpuInfoService {

    @Autowired
    private IPmsSpuInfoDescService spuInfoDescService;

    @Autowired
    private IPmsSpuImagesService spuImagesService;

    @Autowired
    private IPmsProductAttrValueService productAttrValueService;

    @Autowired
    private IPmsAttrService attrService;

    @Autowired
    private IPmsSkuInfoService skuInfoService;

    @Autowired
    private IPmsSkuImagesService skuImagesService;

    @Autowired
    private IPmsSkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    private ICouponFeignService couponFeignService;

    @Autowired
    private IWareFeignService wareFeignService;

    @Autowired
    private ICategoryService categoryService;

    @Autowired
    private IPmsBrandService brandService;

    @Autowired
    private HttpServletResponse response;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private ISearchFeignService searchFeignService;

    @Override
    public IPage<PmsSpuInfo> getPmsSpuInfoPage(QueryVo<PmsSpuInfo> queryVo) {

        Page<PmsSpuInfo> paramPage = new Page<>();

        paramPage.setCurrent(queryVo.getCurrentPage());

        paramPage.setSize(queryVo.getPageSize());

        QueryWrapper<PmsSpuInfo> wrapper = new QueryWrapper<>();

        PmsSpuInfo pmsSpuInfo = queryVo.getPayload();

        if(!ObjectUtils.isEmpty(pmsSpuInfo)){
            if(StringUtils.hasText(pmsSpuInfo.getSpuName())){
                wrapper.like("spu_name", pmsSpuInfo.getSpuName());
            }
            if(pmsSpuInfo.getPublishStatus() != null){
                wrapper.eq("publish_status", pmsSpuInfo.getPublishStatus());
            }
            if(pmsSpuInfo.getCatalogId() != null){
                wrapper.eq("catalog_id", pmsSpuInfo.getCatalogId());
            }
            if(pmsSpuInfo.getBrandId() != null){
                wrapper.eq("brand_id", pmsSpuInfo.getBrandId());
            }
        }
        if(!ObjectUtils.isEmpty(queryVo.getStartTime())){
            wrapper.gt("create_time", queryVo.getStartTime());
        }
        if(!ObjectUtils.isEmpty(queryVo.getEndTime())){
            wrapper.lt("create_time", queryVo.getEndTime());
        }
        wrapper.orderByDesc("create_time");

        Page<PmsSpuInfo> page = this.page(paramPage, wrapper);
            List<PmsSpuInfo> spuInfos = page.getRecords();
            if(!CollectionUtils.isEmpty(spuInfos)){

                List<Long> brandIds = spuInfos.stream().map(PmsSpuInfo::getBrandId).collect(Collectors.toList());
                List<Long> catalogIds = spuInfos.stream().map(PmsSpuInfo::getCatalogId).collect(Collectors.toList());
                List<PmsBrand> brands = brandService.list(new QueryWrapper<PmsBrand>().select("brand_id","name").in("brand_id", brandIds));

                Map<Long, String> brandMap = brands.stream().collect(Collectors.toMap(PmsBrand::getBrandId, PmsBrand::getName, (v, v1) -> v));
                List<PmsCategory> categories = categoryService.list(new QueryWrapper<PmsCategory>().select("cat_id","name").in("cat_id", catalogIds));

                Map<Long, String> categoryMap = categories.stream().collect(Collectors.toMap(PmsCategory::getCatId, PmsCategory::getName, (v, v1) -> v));

                spuInfos.forEach(s->{
                    s.setBrandName(brandMap.get(s.getBrandId()));
                    s.setCatalogName(categoryMap.get(s.getCatalogId()));
                });
            }


            return page;
        }

    @Override
    @GlobalTransactional
    @Transactional(transactionManager = "transactionManagerPms", rollbackFor = Exception.class)
    public boolean saveSpuInfo(SpuSaveVo vo) {
        PmsSpuInfo spu = new PmsSpuInfo();
        BeanUtils.copyProperties(vo, spu);
        spu.setPublishStatus(ProductConstant.ProductStatusEnum.NEW_SPU.getCode());
        this.save(spu);
        List<String> decript = vo.getDecript();
        PmsSpuInfoDesc pmsSpuInfoDesc = new PmsSpuInfoDesc();

        pmsSpuInfoDesc.setSpuId(spu.getId());
        pmsSpuInfoDesc.setDecript(String.join(",", decript));

        spuInfoDescService.save(pmsSpuInfoDesc);

        spuImagesService.saveSpuImages(spu.getId(), vo.getImages());

        List<BaseAttr> baseAttrs = vo.getBaseAttrs();

        List<PmsProductAttrValue> productAttrValues = baseAttrs.stream().map(attr -> {

            PmsProductAttrValue attrValue = new PmsProductAttrValue();
            attrValue.setAttrId(attr.getAttrId());

            PmsAttr pmsAttr = attrService.getById(attr.getAttrId());

            attrValue.setAttrName(pmsAttr.getAttrName());
            attrValue.setAttrValue(attr.getAttrValues());
            attrValue.setQuickShow(attr.getShowDesc());
            attrValue.setSpuId(spu.getId());

            return attrValue;
        }).collect(Collectors.toList());

        productAttrValueService.saveBatch(productAttrValues);
        SpuBoundTo spuBoundTo = new SpuBoundTo();
        BeanUtils.copyProperties(vo.getBounds(), spuBoundTo);
        spuBoundTo.setSpuId(spu.getId());
        AsyncContext asyncContext = request.startAsync(request, response);
        R run = PmsToSmsThreadPool.run(() -> {
            couponFeignService.saveSpuBounds(spuBoundTo);
        }, asyncContext);

        List<Sku> skus = vo.getSkus();
        if(!CollectionUtils.isEmpty(skus)){
            skus.forEach(sku->{
                String defaultImg = "";
                List<Images> skuImages = sku.getImages();
                for (Images img : skuImages) {
                    if (img.getDefaultImg() == 1) {
                        defaultImg = img.getImgUrl();
                    }
                }
                PmsSkuInfo skuInfo = new PmsSkuInfo();

                BeanUtils.copyProperties(sku, skuInfo);

                skuInfo.setBrandId(spu.getBrandId());
                skuInfo.setCatalogId(spu.getCatalogId());
                skuInfo.setSaleCount(0L);
                skuInfo.setSpuId(spu.getId());
                skuInfo.setSkuDefaultImg(defaultImg);

                skuInfoService.save(skuInfo);

                Long skuId = skuInfo.getSkuId();

                List<PmsSkuImages> pmsSkuImages = sku.getImages().stream().map(img -> {
                    PmsSkuImages images = new PmsSkuImages();
                    images.setDefaultImg(img.getDefaultImg());
                    images.setImgUrl(img.getImgUrl());
                    images.setSkuId(skuId);
                    return images;
                }).filter(e-> StringUtils.hasText(e.getImgUrl())).collect(Collectors.toList());

                skuImagesService.saveBatch(pmsSkuImages);

                List<Attr> attrs = sku.getAttrs();

                List<PmsSkuSaleAttrValue> saleAttrs = attrs.stream().map(attr -> {
                    PmsSkuSaleAttrValue saleAttr = new PmsSkuSaleAttrValue();

                    BeanUtils.copyProperties(attr, saleAttr);
                    saleAttr.setSkuId(skuId);
                    return saleAttr;
                }).collect(Collectors.toList());

                skuSaleAttrValueService.saveBatch(saleAttrs);

                SkuReductionTo reductionTo = new SkuReductionTo();
                BeanUtils.copyProperties(sku, reductionTo);
                reductionTo.setSkuId(skuId);

                reductionTo.setMemberPrice(sku.getMemberPrice().stream().map(e->{
                    com.youbug.common.to.MemberPrice memberPrice = new com.youbug.common.to.MemberPrice();
                    BeanUtils.copyProperties(e, memberPrice);
                    return memberPrice;
                }).collect(Collectors.toList()));
                if(reductionTo.getFullCount()>0 && reductionTo.getFullPrice().compareTo(new BigDecimal("0"))==1){
                    couponFeignService.saveSkuReduction(reductionTo);
                }
            });
        }
        return false;
    }

    @Override
    public Boolean up(Long spuId) {
        List<PmsSkuInfo> skus = skuInfoService.list(new QueryWrapper<PmsSkuInfo>().eq("spu_id", spuId));

        List<Long> brandIds = skus.stream().map(PmsSkuInfo::getBrandId).collect(Collectors.toList());

        List<Long> skuIds = skus.stream().map(PmsSkuInfo::getSkuId).collect(Collectors.toList());

        List<Long> catalogIds = skus.stream().map(PmsSkuInfo::getCatalogId).collect(Collectors.toList());

        List<PmsBrand> brands = brandService.listByIds(brandIds);

        Map<Long, PmsBrand> brandMap = brands.stream().collect(Collectors.toMap(PmsBrand::getBrandId, e-> e, (v, v1) -> v));

        List<PmsCategory> categories = categoryService.listByIds(catalogIds);

        Map<Long, String> categoryMap = categories.stream().collect(Collectors.toMap(PmsCategory::getCatId, PmsCategory::getName, (v, v1) -> v));

        List<SkuEsModel.Attr> attrs = getEsModelAttrs(spuId);

        List<SkuHasStockTo> hasStockVos =  wareFeignService.getSkuHasStock(skuIds);

        Map<Long, Boolean> hasStockMap = hasStockVos.stream().collect(Collectors.toMap(SkuHasStockTo::getSkuId, SkuHasStockTo::getHasStock, (v, v1) -> v));

        List<SkuEsModel> models = skus.stream().map(sku -> {
            SkuEsModel model = new SkuEsModel();

            BeanUtils.copyProperties(sku, model);
            PmsBrand brand = brandMap.get(sku.getBrandId());
            model.setSkuPrice(sku.getPrice());
            model.setSkuImg(sku.getSkuDefaultImg());
            model.setHasStock(hasStockMap.get(sku.getSkuId()));// 来自库存服务
            model.setHotScore(0L);
            model.setBrandName(brand!=null?brand.getName():null);
            model.setBrandImg(brand!=null?brand.getLogo():null);

            model.setCatalogName(categoryMap.get(sku.getCatalogId()));
            model.setAttrs(attrs);

            return model;
        }).collect(Collectors.toList());
        searchFeignService.productStatusUp(models);
        PmsSpuInfo pmsSpuInfo = new PmsSpuInfo();
        pmsSpuInfo.setId(spuId);
        pmsSpuInfo.setPublishStatus(ProductConstant.ProductStatusEnum.SPU_UP.getCode());
        this.updateById(pmsSpuInfo);
        return true;
    }

    private List<SkuEsModel.Attr> getEsModelAttrs(Long spuId) {
        List<PmsProductAttrValue> baseAttrs = productAttrValueService.getPmsSpuBaseAttrs(spuId);

        List<Long> baseAttrIds = baseAttrs.stream().map(PmsProductAttrValue::getAttrId).collect(Collectors.toList());

        List<Long> searchAttrIds = attrService.selectSearchAttrs(baseAttrIds);

        return baseAttrs.stream().filter(a -> {
            return searchAttrIds.contains(a.getAttrId());
        }).map(a -> {
            SkuEsModel.Attr attr = new SkuEsModel.Attr();
            attr.setAttrId(a.getAttrId());
            attr.setAttrName(a.getAttrName());
            attr.setAttrValue(a.getAttrValue());
            return attr;
        }).collect(Collectors.toList());
    }

    @Override
    public Boolean down(Long spuId) {

        searchFeignService.productStatusDown(spuId);
        PmsSpuInfo pmsSpuInfo = new PmsSpuInfo();
        pmsSpuInfo.setId(spuId);
        pmsSpuInfo.setPublishStatus(ProductConstant.ProductStatusEnum.SPU_DOWN.getCode());
        boolean update = this.updateById(pmsSpuInfo);

        return update;
    }

    @Override
    public PmsSpuInfo getSpuInfoBySkuId(Long skuId) {

        PmsSkuInfo skuInfo = skuInfoService.getById(skuId);
        PmsSpuInfo spuInfo = this.getById(skuInfo.getSpuId());

        return spuInfo;
    }

    @Override
    public boolean removeSpu(Long skuId) {


        return false;
    }
}
